﻿using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using ServiceStack.Redis;
using System;
using System.Threading;
using System.Threading.Tasks;

namespace Lesson06SessionMVC.Controllers
{
    [ApiController]
    [Route("[controller]/[action]")]
    public class HomeController : ControllerBase
    {
        private readonly ILogger<HomeController> _logger;
        private readonly RedisClient _redisClient;

        public HomeController(ILogger<HomeController> logger, RedisClient redisClient)
        {
            _logger = logger;
            _redisClient = redisClient;
        }

        /// <summary>
        /// 初始化数据库
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public async Task<bool> Init()
        {
            _redisClient.FlushDb();
            //票的库存
            _redisClient.Set<int>("inventoryNum", 10);
            //订单数
            _redisClient.Set<int>("orderNum", 0);

            return await Task.FromResult(true);
        }

        /// <summary>
        /// 抢购过程模拟
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public async Task<string> Index(long UserId)
        {
            var token = "UserId_" + UserId.ToString();
            return await Task.FromResult(Show(_redisClient, token, "Order", TimeSpan.FromMilliseconds(500)));
        }

        //这个是阻塞的锁
        private string Show(RedisClient client, string clientKey, string key, TimeSpan timeout)
        {
            string output = null;
            //尝试在redis中创建一个字符串结构缓存，方法传入的key，value为锁的过期时间timeout的时间戳。
            //加了这句话，下面所有的代码都是单线程的执行
            //这里拿不到锁时，超时。会报异常，这里面应该把这个异常捕获并打印出来
            try
            {
                using (var datalock = client.AcquireLock("DataLock:" + key, timeout))
                {
                    //库存数量
                    var inventory = client.Get<int>("inventoryNum");
                    if (inventory > 0)
                    {
                        client.Set<int>("inventoryNum", inventory - 1);
                        //订单数量
                        var orderNum = client.Incr("orderNum");
                        output = $"{clientKey}抢购成功*****,库存：{inventory},订单数量：{orderNum}";
                    }
                    else
                    {
                        output = $"{clientKey}抢购失败，没有库存";
                    }
                }
            }
            catch (Exception)
            {
                output = $"{clientKey}抢购失败，等待拿锁超时";
            }

            Console.WriteLine(output);
            return output;
        }

    }
}
